----------------------------------------------------------------------------------------------------

                                    SOME USEFUL COERCION

Lua's dynamic setting of data types is useful, but can be surprisingly restrictive! Try doing any
arithmetic with a Boolean value to see how that works (fails!). Printing it might fail too, if a
string is expected. The following method will fix this problem.

  Boolean and "TRUE" or "FALSE"  --Coerces a boolean to a string (or number: Boolean and 1 or 0).

A similar but less dramatic problem arises when you already know a number can be considered as a
string, or vice versa, with no need to test it, or to use 'tonumber' to convert a string. LuaTools
is designed to make it easier to exclude library code from tools that don't needed it, so if using
its functions to act on strings or numbers, they will test the input for validity. Simple coercion
is better than allowing an error to arise when you know that simple coercion is the only thing you
need to prevent it!

  N..""                          --Coerces a number to a string.
  "N"+0                          --Coerces a numeric string to a number.

These will only fail if the value N is unable to be converted, in which case tonumber might usually
fail too. As 'tonumber' needs the base library to work, it is better to think carefully about the
data types in the first place, and not to expect Lua to do everything. If the problem is a string
of HEX digits that can't be interpreted as a decimal number, use the a.int() and a.num() functions
to do the conversion.

----------------------------------------------------------------------------------------------------

                                    TESTING THE ARG TABLE

Lua's arg table takes command line aruments and switches, etc. The precise details vary between
versions, especially what happens to arg[0] and arg[-1]. LuaTools has modifications to make the
three Lua versiosn used behave the same way. This is very important for an independent executable
compiled with Luac. The following code will test Lua's arg table. Incidentally, testing arg[-1]
in LuaTools is useful when a script needs to know if it's running in Lua, or as an independently
compiled program. There is no use of table.getn, so the table library can be excluded from a tool
with no danger of this failing to work.

  C=0  N=5  repeat  N=N-1  if arg[N]==nil then  arg[N]="nil"  else  C=C+1  end  until N==1
  S=arg[0].."\n"..arg[1].."\n"..arg[2].."\n"..arg[3].."\n"..arg[4].."\n"..C  a.msg(S)

If the executable was compiled with the Luac -w switch, dragging file icons onto the executable's
icon will cause it to show a list of up to five arguments (including the executable's full path
in arg[0]) as usual, but there will be no console window.

If the f.pne() function is used on the paths, the full path, name, and extension in long and
short formats is available and parsed into substrings for easy use, as well as getting the file
or directory attributes if needed.

----------------------------------------------------------------------------------------------------

                                   FIXING NEWLINE TROUBLE

Using a.tab() can prepare text files as arrays, but unlike using io.lines, CRLF newlines must be
reduced to CR or LF. Both functions a.tab() and a.str() use single-character separators, passed
as strings, but only the first character is used, so don't add more!

  --X starts as a file path, then holds a file.
  X=f.get(X)  X=string.gsub(X,"\r\n","\n")  X=string.gsub(X,"\n\r","\n")  X=string.gsub(X,"\r","\n")

The Lua example above will handle files with mixed DOS/Unix/Mac newlines and is simple and fast.
Documents based on multiple tools contributing to them, such as copy-paste from web sources, or
from partial optical character recognition scans, or people with different machines contributing
text content to a single project, often result in these mixed newlines in one file. The Lua code
above will clean them with minimal disruption of the intended line spacing and formatting, while
leaving the result very easy to re-save with LF converted to CR for a Mac, or to CRLF for Windows.
This reduction to one character '\n' will also save you no end of pain when trying to match string
patterns extracted from text files.

----------------------------------------------------------------------------------------------------

                                 THE AMAZING POWERS OF GSUB

There are more self-iterating functions in Lua than there once were, but the names and actions
are not consistent between versions. The only one that is, is 'string.gsub()', which in LuaTools
is accessible with that naming convention in Lua v4.0.1 as it is in the two versions of Lua v5.

The following function was written for Lua v5.1.4 (used in wxLua v2.8.7 at the time of writing).

  for X,F,C in string.gfind(S,"(GPRMC,.-,(.),%S-)\*(%x%x)") do
    if (F=="A" and Checksum(X)==C) then  table.insert(TABLE,X)  VF=VF+1  else  IF=IF+1  end
  end

That was working code, kept intact to show how easy it is to rewrite it here for string.gsub().
The only thing that changes is the control block structure and the way three values are passed
to the internal code.

  string.gsub(S,"(GPRMC,.-,(.),%S-)%*(%x%x)",function(X,F,C)
    if (F=="A" and Checksum(X)==C) then  table.insert(TABLE,X)  VF=VF+1  else  IF=IF+1  end
  end)

Note that the string returned by string.gsub() is ignored, but it may be useful to modify it
and keep it for something.. The string.gsub() function, especially used with its own internal
function, is probably the single most powerful thing in all of Lua. It's worth developing tools
in Lua just to have access to it!

By doing this, you don't have to worry about lack of the 'ipairs' method, or name mismatches
like string.gfind() vs string.gmatch() let alone the total lack of either in Lua v4.0.1! There
is no penalty for this, it's just as fast, though Lua v4.0.1 might complain of lack of access
to a variable in 'outer scope', in which case make said variable a global. That will slow it
down but not excessively so, and the convenience of exact compatibility in all 3 versions of
Lua in LuaTools will probably make up for it on most tasks. Aim for compatibility because it
helps to write code than works in any version of Lua, anywhere, not just in LuaTools! You can
always optimise choices for a specific version later.
